package org.jasig.cas.ext.pac4j.plugin.weixin;

import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.lang3.StringUtils;
import org.jasig.cas.ext.pac4j.plugin.weibo.WeiboProfile;
import org.pac4j.core.client.BaseClient;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.exception.HttpCommunicationException;
import org.pac4j.oauth.client.BaseOAuth20Client;
import org.pac4j.oauth.credentials.OAuthCredentials;
import org.pac4j.oauth.profile.JsonHelper;
import org.scribe.model.*;

/**
 * 此类用于处理CAS与微信的OAUTH通信
 *
 * @author b2c021
 */
public class WeiXinClient extends BaseOAuth20Client<WeiXinProfile> {

    private final static WeiXinAttributesDefinition WEI_XIN_ATTRIBUTES = new WeiXinAttributesDefinition();

    public WeiXinClient() {
    }

    @Override
    protected BaseClient<OAuthCredentials, WeiXinProfile> newClient() {
        WeiXinClient newClient = new WeiXinClient();
        return newClient;
    }

    @Override
    protected void internalInit() {
        super.internalInit();
        WeiXinApi20 api = new WeiXinApi20();
        this.service = new WeiXinOAuth20ServiceImpl(api, new OAuthConfig(this.key, this.secret, this.callbackUrl, SignatureType.Header, null, null),
                this.connectTimeout, this.readTimeout, this.proxyHost, this.proxyPort);
    }

    @Override
    protected String getProfileUrl() {
        return "https://api.weixin.qq.com/sns/userinfo";
    }

    @Override
    protected WeiXinProfile extractUserProfile(String body) {
        WeiXinProfile profile = new WeiXinProfile();
        final JsonNode json = JsonHelper.getFirstNode(body);
        if (null != json) {
            //unionId为联合ID,绑定到开放平台多个公众号拥有同一个unionId
            Object openId = JsonHelper.get(json, WeiXinAttributesDefinition.UNION_ID);
            if (openId == null) {
                openId = JsonHelper.get(json, WeiXinAttributesDefinition.OPEN_ID);
            }
            profile.setId(openId);
            for (final String attribute : WEI_XIN_ATTRIBUTES.getPrincipalAttributes()) {
                Object value = JsonHelper.get(json, attribute);
                profile.addAttribute(attribute, value);
                if (StringUtils.equals(attribute, WeiXinAttributesDefinition.NICK_NAME)) {
                    profile.addAttribute(WeiXinAttributesDefinition.USERNAME, JsonHelper.get(json, attribute));
                }
                if (StringUtils.equals(attribute, WeiXinAttributesDefinition.HEAD_IMG_URL)) {
                    profile.addAttribute(WeiXinAttributesDefinition.PICTURE_URL, value);
                }
            }
        }
        return profile;
    }

    /**
     * 需求state元素
     */
    @Override
    protected boolean requiresStateParameter() {
        return false;
    }

    @Override // Cancelled 取消
    protected boolean hasBeenCancelled(WebContext context) {
        return false;
    }

    @Override
    protected String sendRequestForData(final Token accessToken, final String dataUrl) {
        logger.debug("accessToken : {} / dataUrl : {}", accessToken, dataUrl);
        final long t0 = System.currentTimeMillis();
        final ProxyOAuthRequest request = createProxyRequest(dataUrl);
        this.service.signRequest(accessToken, request);

        final Response response = request.send();
        final int code = response.getCode();
        final String body = response.getBody();
        final long t1 = System.currentTimeMillis();
        logger.debug("Request took : " + (t1 - t0) + " ms for : " + dataUrl);
        logger.debug("response code : {} / response body : {}", code, body);
        if (code != 200) {
            logger.error("Failed to get data, code : " + code + " / body : " + body);
            throw new HttpCommunicationException(code, body);
        }
        return body;
    }
}
